﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.IO;

namespace HCCapture
{
    public partial class Cammera : IDisposable
    {
        private uint iLastErr = 0;
        private string str;
        private Int32 m_lUserID = -1;
        private Int32 m_lRealHandle = -1;
        private bool m_bInitSDK = false;
        public bool Active { get; set; }
        public string ID { get; set; }

        public string UID { get; set; }

        public string PWD { get; set; }

        public string IP { get; set; }

        public Int32 PORT { get; set; }

        public int Channel { get; set; }

        public int PresetIndex { get; set; }

        public int PrePresetIndex { get; set; }

        public int CaptureInterval { get; set; }

        public string CapJpgPath { get; set; }

        public string MonthPath
        {
            get
            {
                return System.DateTime.Now.ToString("yyMM");
            }
        }

        public string DatePath
        {
            get
            {
                return System.DateTime.Now.ToString("yyyy-MM-dd");
            }
        }

        public Cammera()
        { }

        public Cammera(ref string msg)
        {
            //this.UID = System.Configuration.ConfigurationManager.AppSettings["UID"];
            //this.PWD = System.Configuration.ConfigurationManager.AppSettings["PWD"];
            //this.IP = System.Configuration.ConfigurationManager.AppSettings["IP"];
            //this.PORT = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["PORT"]);
            //this.Channel = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["Channel"]);            
            //this.CaptureInterval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["CaptureInterval"]) * 1000; //秒为单位
            //this.CapJpgPath = System.Configuration.ConfigurationManager.AppSettings["CapJpgPath"];

            //初始化设备
            this.Initialize(ref msg);
            //判断图片抓取路径是否存在
            //按月存放图片防止一个目录下图片过多
            //this.CapJpgPath = string.Format(@"{0}\{1}",this.CapJpgPath.TrimEnd(new char[]{'/','\\'}),System.DateTime.Now.ToString("yyMM"));
            //if (!FileHelper.IsExistDirectory(this.CapJpgPath))
            //    FileHelper.CreateDirectory(this.CapJpgPath);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="msg"></param>
        public void Initialize(ref string msg)
        {
            //判断图片抓取路径是否存在
            //按月存放图片防止一个目录下图片过多
            //this.MonthPath = System.DateTime.Now.ToString("yyMM");
            this.CapJpgPath = string.Format(@"{0}\{1}", this.CapJpgPath.TrimEnd(new char[] { '/', '\\' }), this.ID);
        }

        /// <summary>
        /// 创建本地目录
        /// </summary>
        public void CreateLocalPath()
        {
            if (DevConfig.Mode != SaveMode.仅FTP) //只ftp上传本地不创建目录
            {
                var mPath = (DevConfig.Mode == SaveMode.本地按日期) ? System.IO.Path.Combine(this.CapJpgPath, this.DatePath) : Path.Combine(this.CapJpgPath, this.MonthPath, this.DatePath);
                if (!FileHelper.IsExistDirectory(mPath))
                {
                    FileHelper.CreateDirectory(mPath);
                }
            }
        }

        /// <summary>
        /// 创建ftp目录
        /// </summary>
        /// <param name="ftp"></param>
        public void CreateFtpPath(FtpWeb ftp)
        {
            //根目录
            //FtpClient.Instance.Ftp.GotoDirectory("", true);
            //FtpWeb ftp = new FtpWeb(this.IP, "", this.UID, this.PWD);
            if (!ftp.DirectoryExist(DevConfig.ftpClient.Path))
                ftp.MakeDir(DevConfig.ftpClient.Path);
            ftp.GotoDirectory(DevConfig.ftpClient.Path, false);
            if (!ftp.DirectoryExist(this.ID))
                ftp.MakeDir(this.ID);
            ftp.GotoDirectory(this.ID, false);

            if (!ftp.DirectoryExist(this.MonthPath))
                ftp.MakeDir(this.MonthPath);
            ftp.GotoDirectory(this.MonthPath, false);

            if (!ftp.DirectoryExist(this.DatePath))
                ftp.MakeDir(this.DatePath);
            ftp.GotoDirectory(this.DatePath, false);
        }


        /// <summary>
        //登录设备
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool LogIn(ref string msg)
        {
            if (m_lUserID < 0)
            {
                string DVRIPAddress = this.IP; //设备IP地址或者域名
                Int32 DVRPortNumber = this.PORT;//设备服务端口号
                string DVRUserName = this.UID;//设备登录用户名
                string DVRPassword = this.PWD;//设备登录密码

                CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();

                //登录设备 Login the device
                m_lUserID = CHCNetSDK.NET_DVR_Login_V30(DVRIPAddress, DVRPortNumber, DVRUserName, DVRPassword, ref DeviceInfo);
                if (m_lUserID < 0)
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = "NET_DVR_Login_V30 failed, error code= " + iLastErr; //登录失败，输出错误号
                    msg = this.ID + ":" + str;
                    return false;
                }
                else
                {
                    //登录成功
                    msg = this.ID + ":Login Success";
                    return true;
                }
            }
            else
            {
                //注销登录 Logout the device
                if (m_lRealHandle >= 0)
                {
                    msg = this.ID + ":Please stop live view firstly";
                    return false;
                }

                if (!CHCNetSDK.NET_DVR_Logout(m_lUserID))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    msg = this.ID + ":NET_DVR_Logout failed, error code= " + iLastErr;
                    return false;
                }
                m_lUserID = -1;
                msg = "LogOut...";
                return false;
            }
        }


        /// <summary>
        //登出设备
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool LogOut(ref string msg)
        {
            //注销登录 Logout the device
            if (m_lUserID >= 0)
            {
                if (m_lRealHandle >= 0)
                {
                    msg = "Please stop live view firstly";
                    return false;
                }

                if (!CHCNetSDK.NET_DVR_Logout(m_lUserID))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    msg = "NET_DVR_Logout failed, error code= " + iLastErr;
                    return false;
                }
                m_lUserID = -1;
                msg = "LogOut...";
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 预览设备
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="msg"></param>
        public void Preview(IntPtr handle, ref string msg)
        {
            if (m_lUserID < 0)
            {
                msg = this.ID + ":Please login the device firstly";
                return;
            }

            if (m_lRealHandle < 0)
            {
                CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
                lpPreviewInfo.hPlayWnd = handle;//预览窗口
                lpPreviewInfo.lChannel = this.Channel;//预te览的设备通道
                lpPreviewInfo.dwStreamType = 0;//码流类型：0-主码流，1-子码流，2-码流3，3-码流4，以此类推
                lpPreviewInfo.dwLinkMode = 0;//连接方式：0- TCP方式，1- UDP方式，2- 多播方式，3- RTP方式，4-RTP/RTSP，5-RSTP/HTTP 
                lpPreviewInfo.bBlocked = true; //0- 非阻塞取流，1- 阻塞取流
                lpPreviewInfo.dwDisplayBufNum = 15; //播放库播放缓冲区最大缓冲帧数

                CHCNetSDK.REALDATACALLBACK RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数
                IntPtr pUser = new IntPtr();//用户数据

                //打开预览 Start live view 
                m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null/*RealData*/, pUser);
                if (m_lRealHandle < 0)
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = this.ID + ":NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败，输出错误号
                    msg = str;
                    return;
                }
                else
                {
                    //预览成功
                    msg = "Live View";
                }
            }
            else
            {
                //停止预览 Stop live view 
                if (!CHCNetSDK.NET_DVR_StopRealPlay(m_lRealHandle))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = this.ID + ":NET_DVR_StopRealPlay failed, error code= " + iLastErr;
                    msg = str;
                    return;
                }
                m_lRealHandle = -1;
                msg = "Stop Live View";

            }
            return;
        }


        /// <summary>
        /// 转到预置点
        /// </summary>
        /// <param name="msg"></param>
        public bool PTZPreset_Other(int index)
        {
            string msg = "";
            if (m_lUserID < 0)
            {
                msg = this.ID + ":Please login the device firstly";
                return false;
            }
            return CHCNetSDK.NET_DVR_PTZPreset_Other(m_lUserID, this.Channel, 39, uint.Parse(index + ""));
        }



        public void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, ref byte pBuffer, UInt32 dwBufSize, IntPtr pUser)
        { }

        /// <summary>
        /// 停止预览
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="msg"></param>
        public string StopPreview()
        {
            string msg = "";
            //停止预览 Stop =""e view 
            if (m_lRealHandle >= 0)
            {
                if (!CHCNetSDK.NET_DVR_StopRealPlay(m_lRealHandle))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = "NET_DVR_StopRealPlay failed, error code= " + iLastErr;
                    msg = str;
                    return "";
                }
                m_lRealHandle = -1;
                msg = this.ID + "：Stop Live View";
            }
            return msg;
        }


        /// <summary>
        /// 抓取 jpeg 图片
        /// </summary>
        /// <param name="sJpegPicFileName"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string CaptureJpeg(bool isUpload = false)
        {
            try
            {
                this.CreateLocalPath();
                //图片保存路径和文件名 the path and file name to save
                string jpgfileName = this.ID + System.DateTime.Now.ToString("yyMMddHHmmss");
                string sJpegPicFileName = DevConfig.Mode == SaveMode.本地按日期 ? Path.Combine(this.CapJpgPath, this.DatePath, this.ID + ".jpg") : string.Format(@"{0}\{1}\{2}\{3}.jpg", this.CapJpgPath.TrimEnd(new char[] { '/', '\\' }), this.MonthPath, this.DatePath, jpgfileName);

                int lChannel = this.Channel; //通道号 Channel number

                CHCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new CHCNetSDK.NET_DVR_JPEGPARA();
                lpJpegPara.wPicQuality = 0; //图像质量 Image quality
                lpJpegPara.wPicSize = 0xff; //抓图分辨率 Picture size: 2- 4CIF，0xff- Auto(使用当前码流分辨率)，抓图分辨率需要设备支持，更多取值请参考SDK文档

                //JPEG抓图 Capture a JPEG picture
                if (!CHCNetSDK.NET_DVR_CaptureJPEGPicture(m_lUserID, lChannel, ref lpJpegPara, sJpegPicFileName))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = "NET_DVR_CaptureJPEGPicture failed, error code= " + iLastErr;
                }
                else
                {
                    if (isUpload)
                    {
                        FtpWeb ftp = new FtpWeb(DevConfig.ftpClient.IP, "", DevConfig.ftpClient.UID, DevConfig.ftpClient.PWD);
                        this.CreateFtpPath(ftp);
                        ftp.Upload(sJpegPicFileName);
                    }
                    str = "saved file is " + sJpegPicFileName;
                }
            }
            catch { }
            return str;
        }


        /// <summary>
        /// 抓取 jpeg 图片到内存
        /// </summary>
        /// <param name="sJpegPicFileName"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string CaptureJpeg_NEW()
        {
            try
            {
                //图片保存路径和文件名 the path and file name to save
                string jpgfileName = this.ID + System.DateTime.Now.ToString("yyMMddHHmmss") + ".jpg";
                //string sJpegPicFileName = string.Format(@"{0}\{1}.jpg", this.CapJpgPath.TrimEnd(new char[] { '/', '\\' }), System.DateTime.Now.ToString("yyMMddHHmmss"));

                int lChannel = this.Channel; //通道号 Channel number

                CHCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new CHCNetSDK.NET_DVR_JPEGPARA();
                lpJpegPara.wPicQuality = 0; //图像质量 Image quality
                lpJpegPara.wPicSize = 0xff; //抓图分辨率 Picture size: 2- 4CIF，0xff- Auto(使用当前码流分辨率)，抓图分辨率需要设备支持，更多取值请参考SDK文档

                uint buffLength = 1024 * 1024;
                uint rtnSize = 0;
                byte[] buff = new byte[buffLength];
                //JPEG抓图 Capture a JPEG picture
                if (!CHCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(m_lUserID, lChannel, ref lpJpegPara, buff, buffLength, ref rtnSize))
                {
                    iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    str = "NET_DVR_CaptureJPEGPicture failed, error code= " + iLastErr;
                }
                else
                {
                    //ftp 上传
                    FtpWeb ftp = new FtpWeb(DevConfig.ftpClient.IP, "", DevConfig.ftpClient.UID, DevConfig.ftpClient.PWD);
                    this.CreateFtpPath(ftp);
                    ftp.Upload(jpgfileName, buff, Convert.ToInt32(rtnSize));

                    str = "saved file is " + jpgfileName;
                }
            }
            catch { }
            return str;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (m_lRealHandle >= 0)
            {
                CHCNetSDK.NET_DVR_StopRealPlay(m_lRealHandle);
            }
            if (m_lUserID >= 0)
            {
                CHCNetSDK.NET_DVR_Logout(m_lUserID);
            }
            if (m_bInitSDK == true)
            {
                CHCNetSDK.NET_DVR_Cleanup();
            }
        }

    }
}
